﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EditMode;

namespace ScriptUtilities
{
    public enum DifficultyLevel
    {
        easy,
        normal,
        hard,
        extreme,
        encore,
    }

    public class PvDatabaseInfo
    {
        public int PvId { get; set; } = 0;

        public string PvIdString => $"pv_{PvId:D3}";

        public string ScriptFileName { get; set; } = string.Empty;

        public string SongName { get; set; } = string.Empty;

        public string SongFileName { get; set; } = string.Empty;

        public int BPM { get; set; } = -1;

        public int Level { get; set; } = -1;

        public DifficultyLevel Difficulty { get; set; } = DifficultyLevel.normal;

        public string PvEditor { get; set; } = "---";

        public List<Performer> Performers { get; set; } = new List<Performer>();

        public List<string> Lyrics { get; set; } = new List<string>();

        public List<Stage> Stages { get; set; } = new List<Stage>();

        public List<EditMode.Diva2nd.Stage> Diva2ndStages { get; set; } = new List<EditMode.Diva2nd.Stage>();

        public List<Effect> Effects { get; set; } = new List<Effect>();

        public List<EditMode.Diva2nd.Effect> Diva2ndEffects { get; set; } = new List<EditMode.Diva2nd.Effect>();

        public List<HandItem> HandItems { get; set; } = new List<HandItem>();

        public List<EditMode.Diva2nd.HandItem> Diva2ndHandItems { get; set; } = new List<EditMode.Diva2nd.HandItem>();

        public List<InstrumentItem> PvItems { get; set; } = new List<InstrumentItem>();

        public List<EditMode.Diva2nd.Motion> Diva2ndMotions { get; set; } = new List<EditMode.Diva2nd.Motion>();

        public List<string> Motions1P { get; set; } = new List<string>();

        public List<string> Motions2P { get; set; } = new List<string>();

        public List<string> Motions3P { get; set; } = new List<string>();

        public string SeName { get; set; } = "01_button1";

        public PvDatabaseInfo(Edit edit, int pvId)
        {
            PvId = pvId;
            BPM = (int)edit.DisplayBpm;
            GetPerformers(edit);
            GetLyrics(edit);
            GetStages(edit);
            GetMotions(edit);
            GetEffects(edit);
            GetHandItems(edit);
            GetPvItems(edit);
            Level = edit.EditDifficulty;
            PvEditor = edit.EditCreator;
            SongName = $"{edit.EditTitle}";
            SongFileName = $"{edit.EditTitle}";
            ScriptFileName = $"{edit.EditTitle}";
        }

        public PvDatabaseInfo(EditMode.Diva2nd.Edit edit, int pvId)
        {
            PvId = pvId;

            BPM = edit.BpmChanges.FirstOrDefault().bpm;
            //GetPerformers(edit);

            //GetLyrics(edit);
            Lyrics = new List<string>(edit.Lyrics);

            //GetStages(edit);
            Diva2ndStages = new List<EditMode.Diva2nd.Stage>(edit.Stages);

            //GetMotions(edit);
            Diva2ndMotions = new List<EditMode.Diva2nd.Motion>(edit.Motions);

            //GetEffects(edit);
            Diva2ndEffects = new List<EditMode.Diva2nd.Effect>(edit.Effects);

            //GetHandItems(edit);
            Diva2ndHandItems = new List<EditMode.Diva2nd.HandItem>(edit.HandItems);

            //GetPvItems(edit);

            //Level = edit.EditDifficulty;
            Level = 10;

            if (edit.Module1 != EditMode.Diva2nd.Module.none)
            {
                Performers.Add(new Performer()
                {
                    Id = 0,
                    Type = Performer.CharaType.VOCAL,
                    Chara = Performer.Character.MIK,
                    //Chara = Performer.GetCharacter(edit.Module1),
                    CharaSize = Performer.Size.NORMAL,
                    PvCostume = Module.初音ミク_オリジナル,
                    //PvCostume = edit.Module1,
                });
            }
            if (edit.Module2 != EditMode.Diva2nd.Module.none)
            {
                Performers.Add(new Performer()
                {
                    Id = 0,
                    Type = Performer.CharaType.VOCAL,
                    Chara = Performer.Character.MIK,
                    //Chara = Performer.GetCharacter(edit.Module1),
                    CharaSize = Performer.Size.NORMAL,
                    PvCostume = Module.初音ミク_オリジナル,
                    //PvCostume = edit.Module1,
                });
            }

            SeName = edit.ButtonSound.ToString().TrimStart('_');

            PvEditor = $"{edit.EditName}";
            SongName = $"{edit.SongName}";
            SongFileName = $"{edit.SongName}";
            ScriptFileName = $"{edit.SongName}";
        }

        public void GetPerformers(Edit edit)
        {
            if (edit.Module1 != Module.なし)
            {
                Performers.Add(new Performer()
                {
                    Id = 0,
                    Type = Performer.CharaType.VOCAL,
                    Chara = Performer.GetCharacter(edit.Module1),
                    CharaSize = Performer.Size.NORMAL,
                    PvCostume = edit.Module1,
                    Back = edit.Module1Back,
                    Face = edit.Module1Face,
                    Neck = edit.Module1Chest,
                    Zujo = edit.Module1Head,
                });
            }
            if (edit.Module2 != Module.なし)
            {
                Performers.Add(new Performer()
                {
                    Id = 1,
                    Type = Performer.CharaType.VOCAL,
                    Chara = Performer.GetCharacter(edit.Module2),
                    CharaSize = Performer.Size.NORMAL,
                    PvCostume = edit.Module2,
                    Back = edit.Module2Back,
                    Face = edit.Module2Face,
                    Neck = edit.Module2Chest,
                    Zujo = edit.Module2Head,
                });
            }
            if (edit.Module3 != Module.なし)
            {
                Performers.Add(new Performer()
                {
                    Id = 2,
                    Type = Performer.CharaType.VOCAL,
                    Chara = Performer.GetCharacter(edit.Module3),
                    CharaSize = Performer.Size.NORMAL,
                    PvCostume = edit.Module3,
                    Back = edit.Module3Back,
                    Face = edit.Module3Face,
                    Neck = edit.Module3Chest,
                    Zujo = edit.Module3Head,
                });
            }
        }

        public void GetLyrics(Edit edit)
        {
            edit.EditLyrics.ForEach(l =>
            {
                var str = $"{l.Lyrics}";
                if (!Lyrics.Contains(str))
                    Lyrics.Add(str);
            });
        }

        public void GetEffects(Edit edit)
        {
            edit.EditEffects.ForEach(e =>
            {
                Effect id = e.EffectID;
                if (!Effects.Contains(id) && id != Effect.なし)
                    Effects.Add(id);
            });
        }

        public void GetHandItems(Edit edit)
        {
            edit.PlayerItemPlayer1s.ForEach(e =>
            {
                HandItem id = (HandItem)e.ItemID;
                if (Enum.IsDefined(typeof(HandItem), id) && !HandItems.Contains(id) && id != (HandItem)Item.なし)
                    HandItems.Add(id);
            });
            edit.PlayerItemPlayer2s.ForEach(e =>
            {
                HandItem id = (HandItem)e.ItemID;
                if (Enum.IsDefined(typeof(HandItem), id) && !HandItems.Contains(id) && id != (HandItem)Item.なし)
                    HandItems.Add(id);
            });
            edit.PlayerItemPlayer3s.ForEach(e =>
            {
                HandItem id = (HandItem)e.ItemID;
                if (Enum.IsDefined(typeof(HandItem), id) && !HandItems.Contains(id) && id != (HandItem)Item.なし)
                    HandItems.Add(id);
            });
        }

        public void GetPvItems(Edit edit)
        {
            edit.PlayerItemPlayer1s.ForEach(e =>
            {
                InstrumentItem id = (InstrumentItem)e.ItemID;
                if (Enum.IsDefined(typeof(InstrumentItem), id) && !PvItems.Contains(id) && id != (InstrumentItem)Item.なし)
                    PvItems.Add(id);
            });
            edit.PlayerItemPlayer2s.ForEach(e =>
            {
                InstrumentItem id = (InstrumentItem)e.ItemID;
                if (Enum.IsDefined(typeof(InstrumentItem), id) && !PvItems.Contains(id) && id != (InstrumentItem)Item.なし)
                    PvItems.Add(id);
            });
            edit.PlayerItemPlayer3s.ForEach(e =>
            {
                InstrumentItem id = (InstrumentItem)e.ItemID;
                if (Enum.IsDefined(typeof(InstrumentItem), id) && !PvItems.Contains(id) && id != (InstrumentItem)Item.なし)
                    PvItems.Add(id);
            });
        }

        public void GetStages(Edit edit)
        {
            edit.EditStages.ForEach(s =>
            {
                Stage str = s.StageID1 == Stage.SPR_EDIT_BLACK ? s.StageID3 : s.StageID1;
                if (!Stages.Contains(str))
                    Stages.Add(str);
            });
        }

        public void GetMotions(Edit edit)
        {
            edit.PlayerMotionPlayer1s.ForEach(m =>
            {
                var str = $"{m.MotionID1}";
                if (!Motions1P.Contains(str))
                    Motions1P.Add(str);
            });
            edit.PlayerMotionPlayer2s.ForEach(m =>
            {
                var str = $"{m.MotionID1}";
                if (!Motions2P.Contains(str))
                    Motions2P.Add(str);
            });
            edit.PlayerMotionPlayer3s.ForEach(m =>
            {
                var str = $"{m.MotionID1}";
                if (!Motions3P.Contains(str))
                    Motions3P.Add(str);
            });
        }

        public List<string> GetPvDb()
        {
            var sb = new StringBuilder();

            sb.AppendLine($"# EditScript.Import : {DateTime.Now.ToShortDateString()}");
            sb.AppendLine($"# --- {PvIdString.ToUpper()} ---");
            //sb.AppendLine($"# This file was generated automatically.");

            sb.AppendLine($"{PvIdString}.bpm={BPM}");

            sb.AppendLine($"{PvIdString}.date={DateTime.Now.Year:D4}{DateTime.Now.Month:D2}{DateTime.Now.Day:D2}");

            ScriptFileName = $"rom/script/pv{PvId:D3}/{ScriptFileName}.dsc";
            sb.AppendLine($"{PvIdString}.difficulty.{Difficulty}.level={Level}");
            sb.AppendLine($"{PvIdString}.difficulty.{Difficulty}.script_file_name={ScriptFileName}");
            sb.AppendLine($"{PvIdString}.difficulty.{Difficulty}.script_format=0x00000000");
            sb.AppendLine($"{PvIdString}.difficulty.{Difficulty}.version=1");

            sb.AppendLine($"# {PvIdString}.disp2d.set_name={PvId:D3}");
            sb.AppendLine($"# {PvIdString}.edit_chara_scale=1");
            sb.AppendLine($"# {PvIdString}.edit=2");

            for (int i = 0; i < Effects.Count; i++)
            {
                sb.AppendLine($"# edit_effect.{i:D2}.name={Effects[i]}");

                if (Enum.TryParse(Effects[i].ToString(), out EffectFile fileId))
                {
                    sb.AppendLine($"{PvIdString}.edit_effect.{i:D2}={(int)fileId:D3}");
                }
                else
                {
                    sb.AppendLine($"{PvIdString}.edit_effect.{i:D2}=666");
                }
            }

            sb.AppendLine($"{PvIdString}.is_extra=1");

            for (int i = 0; i < Lyrics.Count; i++)
                sb.AppendLine($"{PvIdString}.lyric.{i:D3}={Lyrics[i]}");

            for (int i = 0; i < Motions1P.Count; i++)
                sb.AppendLine($"{PvIdString}.motion.{i:D2}={Motions1P[i]}");

            for (int i = 0; i < Motions2P.Count; i++)
                sb.AppendLine($"{PvIdString}.motion2P.{i:D2}={Motions2P[i]}");

            for (int i = 0; i < Motions3P.Count; i++)
                sb.AppendLine($"{PvIdString}.motion3P.{i:D2}={Motions3P[i]}");

            for (int i = 0; i < Performers.Count; i++)
            {
                sb.AppendLine($"{PvIdString}.performer.{Performers[i].Id}.chara={Performers[i].Chara}");
                sb.AppendLine($"# performer.{Performers[i].Id}.item_back.name={Performers[i].Back}");
                sb.AppendLine($"{PvIdString}.performer.{Performers[i].Id}.item_back={(int)Performers[i].Back}");
                sb.AppendLine($"# performer.{Performers[i].Id}.item_face.name={Performers[i].Face}");
                sb.AppendLine($"{PvIdString}.performer.{Performers[i].Id}.item_face={(int)Performers[i].Face}");
                sb.AppendLine($"# performer.{Performers[i].Id}.item_neck.name={Performers[i].Neck}");
                sb.AppendLine($"{PvIdString}.performer.{Performers[i].Id}.item_neck={(int)Performers[i].Neck}");
                sb.AppendLine($"# performer.{Performers[i].Id}.item_zujo.name={Performers[i].Zujo}");
                sb.AppendLine($"{PvIdString}.performer.{Performers[i].Id}.item_zujo={(int)Performers[i].Zujo}");
                sb.AppendLine($"# performer.{Performers[i].Id}.pv_costume.name={Performers[i].PvCostume}");
                sb.AppendLine($"{PvIdString}.performer.{Performers[i].Id}.pv_costume={(int)Performers[i].PvCostume}");
                sb.AppendLine($"{PvIdString}.performer.{Performers[i].Id}.size={Performers[i].CharaSize}");
                sb.AppendLine($"{PvIdString}.performer.{Performers[i].Id}.type={Performers[i].Type}");
            }
            sb.AppendLine($"{PvIdString}.performer.num={Performers.Count}");

            SongFileName = $"rom/sound/song/{SongFileName}.ogg";
            sb.AppendLine($"{PvIdString}.song_file_name={SongFileName}");
            sb.AppendLine($"{PvIdString}.song_name={SongName}");
            sb.AppendLine($"{PvIdString}.song_name_reading={PvIdString}");

            sb.AppendLine($"{PvIdString}.songinfo.arranger={"---"}");
            sb.AppendLine($"{PvIdString}.songinfo.lyrics={"---"}");
            sb.AppendLine($"{PvIdString}.songinfo.music={"---"}");
            sb.AppendLine($"# {PvIdString}.songinfo.pv_editor={PvEditor}");

            sb.AppendLine($"{PvIdString}.sort_index={PvId:D3}");

            sb.AppendLine($"# --- EOF ---");

            return SortDbStrings(sb.ToString());
        }

        public List<string> GetFtPvDb()
        {
            var sb = new StringBuilder();

            sb.AppendLine($"# EditScript.Import : {DateTime.Now.ToShortDateString()}");
            sb.AppendLine($"# --- {PvIdString.ToUpper()} --- {SongName}");

            sb.AppendLine($"{PvIdString}.bpm={BPM}");


            //sb.AppendLine($"# --- SOUND EFFECTS ---");

            //sb.AppendLine($"{PvIdString}.chainslide_failure_name=slide_ng03");
            //sb.AppendLine($"{PvIdString}.chainslide_first_name=slide_long02a");
            //sb.AppendLine($"{PvIdString}.chainslide_sub_name=slide_button08");
            //sb.AppendLine($"{PvIdString}.chainslide_success_name=slide_ok03");

            sb.AppendLine($"{PvIdString}.date={DateTime.Now.Year:D4}{DateTime.Now.Month:D2}{DateTime.Now.Day:D2}");

            ScriptFileName = $"rom/script/{ScriptFileName}.dsc".Replace(' ', '_');

            Level = Helper.Clamp(Level, 0, 20);

            string level = $"PV_LV_{Level / 2:D2}_{((Level % 2 == 0) ? 0 : 5)}";
            sb.AppendLine($"{PvIdString}.difficulty.{Difficulty}.0.edition=0");
            sb.AppendLine($"{PvIdString}.difficulty.{Difficulty}.0.level={level}");
            sb.AppendLine($"{PvIdString}.difficulty.{Difficulty}.0.level_sort_index={PvId}");
            sb.AppendLine($"{PvIdString}.difficulty.{Difficulty}.0.script_file_name={ScriptFileName}");
            sb.AppendLine($"{PvIdString}.difficulty.{Difficulty}.0.script_format=0x00000000");
            sb.AppendLine($"{PvIdString}.difficulty.{Difficulty}.0.version=1");
            sb.AppendLine($"{PvIdString}.difficulty.{Difficulty}.length=1");

            sb.AppendLine($"# --- EDIT ---");

            sb.AppendLine($"{PvIdString}.edit=2");
            sb.AppendLine($"{PvIdString}.edit_chara_scale=1");

            sb.AppendLine($"# --- EFFECTS ---");

            for (int i = 0; i < Effects.Count; i++)
            {
                sb.AppendLine($"# edit_effect.{i:D2}.name={Effects[i]}");

                if (Enum.TryParse(Effects[i].ToString(), out EffectFile fileId))
                {
                    sb.AppendLine($"{PvIdString}.edit_effect.{i:D2}={(int)fileId:D3}");
                }
                else
                {
                    sb.AppendLine($"{PvIdString}.edit_effect.{i:D2}=666");
                }
            }

            sb.AppendLine($"# --- FIELDS ---");
            AppendFields(sb);

            sb.AppendLine($"# --- HAND ITEMS ---");
            for (int i = 0; i < HandItems.Count; i++)
            {
                sb.AppendLine($"# hand_item.{(i + 1):D2}.name={HandItems[i]}");
                if (Enum.IsDefined(typeof(FtHandItem), (FtHandItem)HandItems[i]))
                {
                    sb.AppendLine($"{PvIdString}.hand_item.{(i + 1):D2}={(FtHandItem)HandItems[i]}");
                }
                else
                {
                    sb.AppendLine($"{PvIdString}.hand_item.{(i + 1):D2}=DUMMY");
                }
            }

            sb.AppendLine($"# --- MODIFIERS ---");

            sb.AppendLine($"{PvIdString}.hidden_timing=0.3");
            sb.AppendLine($"{PvIdString}.high_speed_rate=4");

            sb.AppendLine($"# --- LYRICS ---");

            if (Lyrics.Count > 0)
            {
                for (int i = 0; i < Lyrics.Count; i++)
                    sb.AppendLine($"{PvIdString}.lyric.{i:D3}={Lyrics[i]}");
            }
            else
            {
                sb.AppendLine($"{PvIdString}.lyric.{0:D3}={string.Empty}");
            }

            sb.AppendLine($"# --- MOTIONS ---");

            if (Performers.Count > 0)
            {
                for (int i = 0; i < Motions1P.Count; i++)
                {
                    var adjustedMotion = Settings.UserSettings.MotionLookup.FirstOrDefault(m => m.InputMotion == Motions1P[i].ToString());

                    if (!string.IsNullOrEmpty(adjustedMotion.InputMotion) && !string.IsNullOrEmpty(adjustedMotion.OutputMotion))
                    {
                        sb.AppendLine($"# {adjustedMotion.InputMotion} => {adjustedMotion.OutputMotion}");
                        sb.AppendLine($"{PvIdString}.motion.{i:D2}={adjustedMotion.OutputMotion}");
                    }
                    else
                    {
                        sb.AppendLine($"{PvIdString}.motion.{i:D2}={Motions1P[i]}");
                    }
                }
            }

            if (Performers.Count > 1)
            {
                for (int i = 0; i < Motions2P.Count; i++)
                {
                    var adjustedMotion = Settings.UserSettings.MotionLookup.FirstOrDefault(m => m.InputMotion == Motions2P[i].ToString());

                    if (!string.IsNullOrEmpty(adjustedMotion.InputMotion) && !string.IsNullOrEmpty(adjustedMotion.OutputMotion))
                    {
                        sb.AppendLine($"# {adjustedMotion.InputMotion} => {adjustedMotion.OutputMotion}");
                        sb.AppendLine($"{PvIdString}.motion2P.{i:D2}={adjustedMotion.OutputMotion}");
                    }
                    else
                    {
                        sb.AppendLine($"{PvIdString}.motion2P.{i:D2}={Motions2P[i]}");
                    }
                }
            }

            if (Performers.Count > 2)
            {
                for (int i = 0; i < Motions3P.Count; i++)
                {
                    var adjustedMotion = Settings.UserSettings.MotionLookup.FirstOrDefault(m => m.InputMotion == Motions3P[i].ToString());

                    if (!string.IsNullOrEmpty(adjustedMotion.InputMotion) && !string.IsNullOrEmpty(adjustedMotion.OutputMotion))
                    {
                        sb.AppendLine($"# {adjustedMotion.InputMotion} => {adjustedMotion.OutputMotion}");
                        sb.AppendLine($"{PvIdString}.motion3P.{i:D2}={adjustedMotion.OutputMotion}");
                    }
                    else
                    {
                        sb.AppendLine($"{PvIdString}.motion3P.{i:D2}={Motions3P[i]}");
                    }
                }
            }

            sb.AppendLine($"# --- PERFORMERS ---");

            for (int i = 0; i < Performers.Count; i++)
            {
                sb.AppendLine($"{PvIdString}.performer.{Performers[i].Id}.chara={Performers[i].Chara}");

                { // Back
                    sb.AppendLine($"# performer.{Performers[i].Id}.item_back.name={Performers[i].Back}");

                    bool isNull = Performers[i].Back == CustomizeItem.なし;
                    if (isNull)
                        sb.Append("# ");

                    if (Enum.TryParse(Performers[i].Back.ToString(), out FtCustomizeItem ftCustomizeItem))
                        sb.AppendLine($"{PvIdString}.performer.{Performers[i].Id}.item_back={(int)ftCustomizeItem}");
                    else
                        sb.AppendLine($"{PvIdString}.performer.{Performers[i].Id}.item_back={(int)Performers[i].Back}");
                }

                { // Face
                    sb.AppendLine($"# performer.{Performers[i].Id}.item_face.name={Performers[i].Face}");

                    bool isNull = Performers[i].Face == CustomizeItem.なし;
                    if (isNull)
                        sb.Append("# ");

                    if (Enum.TryParse(Performers[i].Face.ToString(), out FtCustomizeItem ftCustomizeItem))
                        sb.AppendLine($"{PvIdString}.performer.{Performers[i].Id}.item_face={(int)ftCustomizeItem}");
                    else
                        sb.AppendLine($"{PvIdString}.performer.{Performers[i].Id}.item_face={(int)Performers[i].Face}");
                }

                { // Neck
                    sb.AppendLine($"# performer.{Performers[i].Id}.item_neck.name={Performers[i].Neck}");

                    bool isNull = Performers[i].Neck == CustomizeItem.なし;
                    if (isNull)
                        sb.Append("# ");

                    if (Enum.TryParse(Performers[i].Neck.ToString(), out FtCustomizeItem ftCustomizeItem))
                        sb.AppendLine($"{PvIdString}.performer.{Performers[i].Id}.item_neck={(int)ftCustomizeItem}");
                    else
                        sb.AppendLine($"{PvIdString}.performer.{Performers[i].Id}.item_neck={(int)Performers[i].Neck}");
                }

                { // Zujo
                    sb.AppendLine($"# performer.{Performers[i].Id}.item_zujo.name={Performers[i].Zujo}");

                    bool isNull = Performers[i].Zujo == CustomizeItem.なし;
                    if (isNull)
                        sb.Append("# ");

                    if (Enum.TryParse(Performers[i].Zujo.ToString(), out FtCustomizeItem ftCustomizeItem))
                        sb.AppendLine($"{PvIdString}.performer.{Performers[i].Id}.item_zujo={(int)ftCustomizeItem}");
                    else
                        sb.AppendLine($"{PvIdString}.performer.{Performers[i].Id}.item_zujo={(int)Performers[i].Zujo}");
                }

                sb.AppendLine($"# performer.{Performers[i].Id}.pv_costume.name={Performers[i].PvCostume}");

                if (Enum.TryParse(Performers[i].PvCostume.ToString(), out FtModules ftModule))
                    sb.AppendLine($"{PvIdString}.performer.{Performers[i].Id}.pv_costume={(int)ftModule}");
                else
                    sb.AppendLine($"{PvIdString}.performer.{Performers[i].Id}.pv_costume={(int)Performers[i].PvCostume}");

                sb.AppendLine($"{PvIdString}.performer.{Performers[i].Id}.size={Performers[i].CharaSize}");
                sb.AppendLine($"{PvIdString}.performer.{Performers[i].Id}.type={Performers[i].Type}");
            }
            sb.AppendLine($"{PvIdString}.performer.num={Performers.Count}");

            sb.AppendLine($"# --- PV ITEMS ---");
            for (int i = 0; i < PvItems.Count; i++)
            {
                sb.AppendLine($"# pv_item.{(i + 1):D2}.name={PvItems[i]}");
                if (Enum.IsDefined(typeof(FtPvItem), (FtPvItem)PvItems[i]))
                {
                    sb.AppendLine($"{PvIdString}.pv_item.{(i + 1):D2}={(FtPvItem)PvItems[i]}");
                }
                else
                {
                    sb.AppendLine($"{PvIdString}.pv_item.{(i + 1):D2}=DUMMY");
                }
            }

            sb.AppendLine($"# --- SABI ---");
            sb.AppendLine($"{PvIdString}.sabi.play_time=1.0");

            sb.AppendLine($"# --- SOUND EFFECTS ---");

            sb.AppendLine($"{PvIdString}.se_name=01_button1");
            sb.AppendLine($"{PvIdString}.slide_name=slide_se13");
            sb.AppendLine($"{PvIdString}.slidertouch_name=slide_windchime");

            sb.AppendLine($"# --- SONG INFO ---");

            SongFileName = $"rom/sound/song/{SongFileName}.ogg".Replace(' ', '_'); ;
            sb.AppendLine($"{PvIdString}.song_file_name={SongFileName}");
            sb.AppendLine($"{PvIdString}.song_name={SongName}");
            sb.AppendLine($"{PvIdString}.song_name_reading={PvIdString}");

            sb.AppendLine($"{PvIdString}.songinfo.arranger={"---"}");
            sb.AppendLine($"{PvIdString}.songinfo.lyrics={"---"}");
            sb.AppendLine($"{PvIdString}.songinfo.music={"---"}");
            sb.AppendLine($"{PvIdString}.songinfo.pv_editor={PvEditor}");

            sb.AppendLine($"# --- MODIFIERS ---");

            sb.AppendLine($"{PvIdString}.sudden_timing=0.6");

            sb.AppendLine($"# --- EOF ---");

            return SortDbStrings(sb.ToString());
        }
        public List<string> GetDiva2ndPvDbAc(string basename)
        {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.AppendLine("# DIVA 2nd EditScript.Import : " + DateTime.Now.ToShortDateString());
            stringBuilder.AppendLine("# --- " + this.PvIdString.ToUpper() + " --- " + this.SongName);
            stringBuilder.AppendLine(string.Format("{0}.bpm={1}", (object)this.PvIdString, (object)this.BPM));
            stringBuilder.AppendLine(string.Format("{0}.date={1:D4}{2:D2}{3:D2}", (object)this.PvIdString, (object)DateTime.Now.Year, (object)DateTime.Now.Month, (object)DateTime.Now.Day));
            this.ScriptFileName = ("rom/script/" + basename + ".dsc");
            this.Level = this.Level.Clamp<int>(0, 20);
            string str = string.Format("PV_LV_{0:D2}_{1}", (object)(this.Level / 2), (object)(this.Level % 2 == 0 ? 0 : 5));
            stringBuilder.AppendLine(string.Format("{0}.difficulty.{1}.edition=0", (object)this.PvIdString, (object)this.Difficulty));
            stringBuilder.AppendLine(string.Format("{0}.difficulty.{1}.level={2}", (object)this.PvIdString, (object)this.Difficulty, (object)(this.Level / 2)));
            stringBuilder.AppendLine(string.Format("{0}.difficulty.{1}.script_file_name={2}", (object)this.PvIdString, (object)this.Difficulty, (object)this.ScriptFileName));
            stringBuilder.AppendLine(string.Format("{0}.difficulty.{1}.script_format=0x11062018", (object)this.PvIdString, (object)this.Difficulty));
            stringBuilder.AppendLine(string.Format("{0}.difficulty.{1}.version=1", (object)this.PvIdString, (object)this.Difficulty));
            stringBuilder.AppendLine("# --- EDIT ---");
            stringBuilder.AppendLine(this.PvIdString + ".disp2d.set_name=440");
            stringBuilder.AppendLine(this.PvIdString + ".disable_calc_motfrm_limit=1");

            if (this.Performers.Count > 1)
            {
                stringBuilder.AppendLine(this.PvIdString + ".duet.num=2");
                stringBuilder.AppendLine(this.PvIdString + ".duet.type=USER_SETTING");
            }

            stringBuilder.AppendLine(this.PvIdString + ".edit=1");
            stringBuilder.AppendLine(this.PvIdString + ".edit_chara_scale=1");

            stringBuilder.AppendLine("# --- EFFECTS ---");
            for (int index = 0; index < this.Diva2ndEffects.Count; ++index)
            {
                int result;
                int.TryParse(this.Diva2ndEffects[index].ToString().Substring("aet_gam_eff".Length), out result);
                stringBuilder.AppendLine(string.Format("{0}.edit_effect.{1:D2}={2:D3}", (object)this.PvIdString, (object)index, (object)result));
            }

            stringBuilder.AppendLine("# --- MODIFIERS ---");
            stringBuilder.AppendLine(this.PvIdString + ".hidden_timing=0.3");
            stringBuilder.AppendLine(this.PvIdString + ".high_speed_rate=4");

            //stringBuilder.AppendLine("# --- FIELDS ---");
            //this.AppendDiva2ndFields(stringBuilder);

            //stringBuilder.AppendLine("# --- HAND ITEMS ---");
            //for (int index = 0; index < this.Diva2ndHandItems.Count; ++index)
            //    stringBuilder.AppendLine(string.Format("{0}.hand_item.{1:D2}={2}", (object)this.PvIdString, (object)(index + 1), (object)this.Diva2ndHandItems[index]));

            stringBuilder.AppendLine("# --- LYRICS ---");
            if (this.Lyrics.Count > 0)
            {
                for (int index = 0; index < this.Lyrics.Count; ++index)
                    stringBuilder.AppendLine(string.Format("{0}.lyric.{1:D2}={2}", (object)this.PvIdString, (object)(index + 1), (object)this.Lyrics[index]));
            }
            else
                stringBuilder.AppendLine(string.Format("{0}.lyric.{1:D3}={2}", (object)this.PvIdString, (object)0, (object)string.Empty));
            stringBuilder.AppendLine("# --- MOTIONS ---");
            if (this.Performers.Count > 0)
            {
                for (int index = 0; index < this.Diva2ndMotions.Count; ++index)
                    stringBuilder.AppendLine(string.Format("{0}.motion.{1:D2}={2}", (object)this.PvIdString, (object)index, (object)this.Diva2ndMotions[index]));
            }
            if (this.Performers.Count > 1)
            {
                for (int index = 0; index < this.Diva2ndMotions.Count; ++index)
                    stringBuilder.AppendLine(string.Format("{0}.motion2P.{1:D2}={2}", (object)this.PvIdString, (object)index, (object)this.Diva2ndMotions[index]));
            }



            //stringBuilder.AppendLine(this.PvIdString + ".is_old_pv=1");
            /*
            stringBuilder.AppendLine("# --- PERFORMERS ---");
            for (int index = 0; index < this.Performers.Count; ++index)
            {
                stringBuilder.AppendLine(string.Format("{0}.performer.{1}.chara={2}", (object)this.PvIdString, (object)this.Performers[index].Id, (object)this.Performers[index].Chara));
                stringBuilder.AppendLine(string.Format("# performer.{0}.item_back.name={1}", (object)this.Performers[index].Id, (object)this.Performers[index].Back));
                if (this.Performers[index].Back == CustomizeItem.なし)
                    stringBuilder.Append("# ");
                FtCustomizeItem result1;
                if (Enum.TryParse<FtCustomizeItem>(this.Performers[index].Back.ToString(), out result1))
                    stringBuilder.AppendLine(string.Format("{0}.performer.{1}.item_back={2}", (object)this.PvIdString, (object)this.Performers[index].Id, (object)(int)result1));
                else
                    stringBuilder.AppendLine(string.Format("{0}.performer.{1}.item_back={2}", (object)this.PvIdString, (object)this.Performers[index].Id, (object)(int)this.Performers[index].Back));
                stringBuilder.AppendLine(string.Format("# performer.{0}.item_face.name={1}", (object)this.Performers[index].Id, (object)this.Performers[index].Face));
                if (this.Performers[index].Face == CustomizeItem.なし)
                    stringBuilder.Append("# ");
                FtCustomizeItem result2;
                if (Enum.TryParse<FtCustomizeItem>(this.Performers[index].Face.ToString(), out result2))
                    stringBuilder.AppendLine(string.Format("{0}.performer.{1}.item_face={2}", (object)this.PvIdString, (object)this.Performers[index].Id, (object)(int)result2));
                else
                    stringBuilder.AppendLine(string.Format("{0}.performer.{1}.item_face={2}", (object)this.PvIdString, (object)this.Performers[index].Id, (object)(int)this.Performers[index].Face));
                stringBuilder.AppendLine(string.Format("# performer.{0}.item_neck.name={1}", (object)this.Performers[index].Id, (object)this.Performers[index].Neck));
                if (this.Performers[index].Neck == CustomizeItem.なし)
                    stringBuilder.Append("# ");
                FtCustomizeItem result3;
                if (Enum.TryParse<FtCustomizeItem>(this.Performers[index].Neck.ToString(), out result3))
                    stringBuilder.AppendLine(string.Format("{0}.performer.{1}.item_neck={2}", (object)this.PvIdString, (object)this.Performers[index].Id, (object)(int)result3));
                else
                    stringBuilder.AppendLine(string.Format("{0}.performer.{1}.item_neck={2}", (object)this.PvIdString, (object)this.Performers[index].Id, (object)(int)this.Performers[index].Neck));
                stringBuilder.AppendLine(string.Format("# performer.{0}.item_zujo.name={1}", (object)this.Performers[index].Id, (object)this.Performers[index].Zujo));
                if (this.Performers[index].Zujo == CustomizeItem.なし)
                    stringBuilder.Append("# ");
                FtCustomizeItem result4;
                if (Enum.TryParse<FtCustomizeItem>(this.Performers[index].Zujo.ToString(), out result4))
                    stringBuilder.AppendLine(string.Format("{0}.performer.{1}.item_zujo={2}", (object)this.PvIdString, (object)this.Performers[index].Id, (object)(int)result4));
                else
                    stringBuilder.AppendLine(string.Format("{0}.performer.{1}.item_zujo={2}", (object)this.PvIdString, (object)this.Performers[index].Id, (object)(int)this.Performers[index].Zujo));
                stringBuilder.AppendLine(string.Format("# performer.{0}.pv_costume.name={1}", (object)this.Performers[index].Id, (object)this.Performers[index].PvCostume));
                FtModules result5;
                if (Enum.TryParse<FtModules>(this.Performers[index].PvCostume.ToString(), out result5))
                    stringBuilder.AppendLine(string.Format("{0}.performer.{1}.pv_costume={2}", (object)this.PvIdString, (object)this.Performers[index].Id, (object)(int)result5));
                else
                    stringBuilder.AppendLine(string.Format("{0}.performer.{1}.pv_costume={2}", (object)this.PvIdString, (object)this.Performers[index].Id, (object)(int)this.Performers[index].PvCostume));
                stringBuilder.AppendLine(string.Format("{0}.performer.{1}.size={2}", (object)this.PvIdString, (object)this.Performers[index].Id, (object)this.Performers[index].CharaSize));
                stringBuilder.AppendLine(string.Format("{0}.performer.{1}.type={2}", (object)this.PvIdString, (object)this.Performers[index].Id, (object)this.Performers[index].Type));
            }
            stringBuilder.AppendLine(string.Format("{0}.performer.num={1}", (object)this.PvIdString, (object)this.Performers.Count));
            */
            stringBuilder.AppendLine("# --- SABI ---");
            stringBuilder.AppendLine(this.PvIdString + ".sabi.play_time=25.0");
            stringBuilder.AppendLine(this.PvIdString + ".sabi.start_time=25.0");
            stringBuilder.AppendLine("# --- SOUND EFFECTS ---");
            stringBuilder.AppendLine(this.PvIdString + ".se_name=" + this.SeName);
            stringBuilder.AppendLine(this.PvIdString + ".slide_name=slide_se13");
            stringBuilder.AppendLine(this.PvIdString + ".slidertouch_name=slide_windchime");
            stringBuilder.AppendLine("# --- SONG INFO ---");
            this.SongFileName = ("rom/sound/song/" + basename + ".ogg");
            stringBuilder.AppendLine(this.PvIdString + ".song_file_name=" + this.SongFileName);
            stringBuilder.AppendLine(this.PvIdString + ".song_name=" + this.SongName);
            stringBuilder.AppendLine(this.PvIdString + ".song_name_reading=" + this.PvIdString);
            stringBuilder.AppendLine(this.PvIdString + ".songinfo.arranger=---");
            stringBuilder.AppendLine(this.PvIdString + ".songinfo.lyrics=---");
            stringBuilder.AppendLine(this.PvIdString + ".songinfo.music=---");
            stringBuilder.AppendLine(this.PvIdString + ".songinfo.pv_editor=" + this.PvEditor);
            //stringBuilder.AppendLine("# --- MODIFIERS ---");
            //stringBuilder.AppendLine(this.PvIdString + ".sudden_timing=0.6");

            stringBuilder.AppendLine(this.PvIdString + ".unlock1P=" + this.Performers[0].Chara.ToString().Substring(0, 3));
            if (this.Performers.Count > 1)
            {
                stringBuilder.AppendLine(this.PvIdString + ".unlock2P=" + this.Performers[0].Chara.ToString().Substring(0, 3));
            }

            stringBuilder.AppendLine("# --- EOF ---");
            return PvDatabaseInfo.SortDbStrings(stringBuilder.ToString());
        }
        public List<string> GetDiva2ndPvDb(string basename = "")
        {
            this.ScriptFileName = basename;
            this.SongFileName = basename;
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.AppendLine("# DIVA 2nd EditScript.Import : " + DateTime.Now.ToShortDateString());
            stringBuilder.AppendLine("# --- " + this.PvIdString.ToUpper() + " --- " + this.SongName);
            stringBuilder.AppendLine(string.Format("{0}.bpm={1}", (object)this.PvIdString, (object)this.BPM));
            stringBuilder.AppendLine(string.Format("{0}.date={1:D4}{2:D2}{3:D2}", (object)this.PvIdString, (object)DateTime.Now.Year, (object)DateTime.Now.Month, (object)DateTime.Now.Day));
            this.ScriptFileName = ("rom/script/" + this.ScriptFileName + ".dsc").Replace(' ', '_');
            this.Level = this.Level.Clamp<int>(0, 20);
            string str = string.Format("PV_LV_{0:D2}_{1}", (object)(this.Level / 2), (object)(this.Level % 2 == 0 ? 0 : 5));
            stringBuilder.AppendLine(string.Format("{0}.difficulty.{1}.0.edition=0", (object)this.PvIdString, (object)this.Difficulty));
            stringBuilder.AppendLine(string.Format("{0}.difficulty.{1}.0.level={2}", (object)this.PvIdString, (object)this.Difficulty, (object)str));
            stringBuilder.AppendLine(string.Format("{0}.difficulty.{1}.0.level_sort_index={2}", (object)this.PvIdString, (object)this.Difficulty, (object)this.PvId));
            stringBuilder.AppendLine(string.Format("{0}.difficulty.{1}.0.script_file_name={2}", (object)this.PvIdString, (object)this.Difficulty, (object)this.ScriptFileName));
            stringBuilder.AppendLine(string.Format("{0}.difficulty.{1}.0.script_format=0x00000000", (object)this.PvIdString, (object)this.Difficulty));
            stringBuilder.AppendLine(string.Format("{0}.difficulty.{1}.0.version=1", (object)this.PvIdString, (object)this.Difficulty));
            stringBuilder.AppendLine(string.Format("{0}.difficulty.{1}.length=1", (object)this.PvIdString, (object)this.Difficulty));
            stringBuilder.AppendLine("# --- EDIT ---");
            stringBuilder.AppendLine(this.PvIdString + ".disable_calc_motfrm_limit=1");
            stringBuilder.AppendLine(this.PvIdString + ".edit=1");
            stringBuilder.AppendLine(this.PvIdString + ".edit_chara_scale=1");
            stringBuilder.AppendLine("# --- EFFECTS ---");
            for (int index = 0; index < this.Diva2ndEffects.Count; ++index)
            {
                int result;
                int.TryParse(this.Diva2ndEffects[index].ToString().Substring("aet_gam_eff".Length), out result);
                stringBuilder.AppendLine(string.Format("{0}.edit_effect.{1:D2}={2:D3}", (object)this.PvIdString, (object)index, (object)result));
            }
            stringBuilder.AppendLine("# --- FIELDS ---");
            this.AppendDiva2ndFields(stringBuilder);
            stringBuilder.AppendLine("# --- HAND ITEMS ---");
            for (int index = 0; index < this.Diva2ndHandItems.Count; ++index)
                stringBuilder.AppendLine(string.Format("{0}.hand_item.{1:D2}={2}", (object)this.PvIdString, (object)(index + 1), (object)this.Diva2ndHandItems[index]));
            stringBuilder.AppendLine("# --- MODIFIERS ---");
            stringBuilder.AppendLine(this.PvIdString + ".hidden_timing=0.3");
            stringBuilder.AppendLine(this.PvIdString + ".high_speed_rate=4");
            stringBuilder.AppendLine(this.PvIdString + ".is_old_pv=1");
            stringBuilder.AppendLine("# --- LYRICS ---");
            if (this.Lyrics.Count > 0)
            {
                for (int index = 0; index < this.Lyrics.Count; ++index)
                    stringBuilder.AppendLine(string.Format("{0}.lyric.{1:D3}={2}", (object)this.PvIdString, (object)(index + 1), (object)this.Lyrics[index]));
            }
            else
                stringBuilder.AppendLine(string.Format("{0}.lyric.{1:D3}={2}", (object)this.PvIdString, (object)0, (object)string.Empty));
            stringBuilder.AppendLine("# --- MOTIONS ---");
            if (this.Performers.Count > 0)
            {
                for (int index = 0; index < this.Diva2ndMotions.Count; ++index)
                    stringBuilder.AppendLine(string.Format("{0}.motion.{1:D2}={2}", (object)this.PvIdString, (object)index, (object)this.Diva2ndMotions[index]));
            }
            if (this.Performers.Count > 1)
            {
                for (int index = 0; index < this.Diva2ndMotions.Count; ++index)
                    stringBuilder.AppendLine(string.Format("{0}.motion2P.{1:D2}={2}", (object)this.PvIdString, (object)index, (object)this.Diva2ndMotions[index]));
            }
            stringBuilder.AppendLine("# --- PERFORMERS ---");
            for (int index = 0; index < this.Performers.Count; ++index)
            {
                stringBuilder.AppendLine(string.Format("{0}.performer.{1}.chara={2}", (object)this.PvIdString, (object)this.Performers[index].Id, (object)this.Performers[index].Chara));
                stringBuilder.AppendLine(string.Format("# performer.{0}.item_back.name={1}", (object)this.Performers[index].Id, (object)this.Performers[index].Back));
                if (this.Performers[index].Back == CustomizeItem.なし)
                    stringBuilder.Append("# ");
                FtCustomizeItem result1;
                if (Enum.TryParse<FtCustomizeItem>(this.Performers[index].Back.ToString(), out result1))
                    stringBuilder.AppendLine(string.Format("{0}.performer.{1}.item_back={2}", (object)this.PvIdString, (object)this.Performers[index].Id, (object)(int)result1));
                else
                    stringBuilder.AppendLine(string.Format("{0}.performer.{1}.item_back={2}", (object)this.PvIdString, (object)this.Performers[index].Id, (object)(int)this.Performers[index].Back));
                stringBuilder.AppendLine(string.Format("# performer.{0}.item_face.name={1}", (object)this.Performers[index].Id, (object)this.Performers[index].Face));
                if (this.Performers[index].Face == CustomizeItem.なし)
                    stringBuilder.Append("# ");
                FtCustomizeItem result2;
                if (Enum.TryParse<FtCustomizeItem>(this.Performers[index].Face.ToString(), out result2))
                    stringBuilder.AppendLine(string.Format("{0}.performer.{1}.item_face={2}", (object)this.PvIdString, (object)this.Performers[index].Id, (object)(int)result2));
                else
                    stringBuilder.AppendLine(string.Format("{0}.performer.{1}.item_face={2}", (object)this.PvIdString, (object)this.Performers[index].Id, (object)(int)this.Performers[index].Face));
                stringBuilder.AppendLine(string.Format("# performer.{0}.item_neck.name={1}", (object)this.Performers[index].Id, (object)this.Performers[index].Neck));
                if (this.Performers[index].Neck == CustomizeItem.なし)
                    stringBuilder.Append("# ");
                FtCustomizeItem result3;
                if (Enum.TryParse<FtCustomizeItem>(this.Performers[index].Neck.ToString(), out result3))
                    stringBuilder.AppendLine(string.Format("{0}.performer.{1}.item_neck={2}", (object)this.PvIdString, (object)this.Performers[index].Id, (object)(int)result3));
                else
                    stringBuilder.AppendLine(string.Format("{0}.performer.{1}.item_neck={2}", (object)this.PvIdString, (object)this.Performers[index].Id, (object)(int)this.Performers[index].Neck));
                stringBuilder.AppendLine(string.Format("# performer.{0}.item_zujo.name={1}", (object)this.Performers[index].Id, (object)this.Performers[index].Zujo));
                if (this.Performers[index].Zujo == CustomizeItem.なし)
                    stringBuilder.Append("# ");
                FtCustomizeItem result4;
                if (Enum.TryParse<FtCustomizeItem>(this.Performers[index].Zujo.ToString(), out result4))
                    stringBuilder.AppendLine(string.Format("{0}.performer.{1}.item_zujo={2}", (object)this.PvIdString, (object)this.Performers[index].Id, (object)(int)result4));
                else
                    stringBuilder.AppendLine(string.Format("{0}.performer.{1}.item_zujo={2}", (object)this.PvIdString, (object)this.Performers[index].Id, (object)(int)this.Performers[index].Zujo));
                stringBuilder.AppendLine(string.Format("# performer.{0}.pv_costume.name={1}", (object)this.Performers[index].Id, (object)this.Performers[index].PvCostume));
                FtModules result5;
                if (Enum.TryParse<FtModules>(this.Performers[index].PvCostume.ToString(), out result5))
                    stringBuilder.AppendLine(string.Format("{0}.performer.{1}.pv_costume={2}", (object)this.PvIdString, (object)this.Performers[index].Id, (object)(int)result5));
                else
                    stringBuilder.AppendLine(string.Format("{0}.performer.{1}.pv_costume={2}", (object)this.PvIdString, (object)this.Performers[index].Id, (object)(int)this.Performers[index].PvCostume));
                stringBuilder.AppendLine(string.Format("{0}.performer.{1}.size={2}", (object)this.PvIdString, (object)this.Performers[index].Id, (object)this.Performers[index].CharaSize));
                stringBuilder.AppendLine(string.Format("{0}.performer.{1}.type={2}", (object)this.PvIdString, (object)this.Performers[index].Id, (object)this.Performers[index].Type));
            }
            stringBuilder.AppendLine(string.Format("{0}.performer.num={1}", (object)this.PvIdString, (object)this.Performers.Count));
            stringBuilder.AppendLine("# --- SABI ---");
            stringBuilder.AppendLine(this.PvIdString + ".sabi.play_time=1.0");
            stringBuilder.AppendLine("# --- SOUND EFFECTS ---");
            stringBuilder.AppendLine(this.PvIdString + ".se_name=" + this.SeName);
            stringBuilder.AppendLine(this.PvIdString + ".slide_name=slide_se13");
            stringBuilder.AppendLine(this.PvIdString + ".slidertouch_name=slide_windchime");
            stringBuilder.AppendLine("# --- SONG INFO ---");
            this.SongFileName = ("rom/sound/song/" + this.SongFileName + ".ogg").Replace(' ', '_');
            stringBuilder.AppendLine(this.PvIdString + ".song_file_name=" + this.SongFileName);
            stringBuilder.AppendLine(this.PvIdString + ".song_name=" + this.SongName);
            stringBuilder.AppendLine(this.PvIdString + ".song_name_reading=" + this.PvIdString);
            stringBuilder.AppendLine(this.PvIdString + ".songinfo.arranger=---");
            stringBuilder.AppendLine(this.PvIdString + ".songinfo.lyrics=---");
            stringBuilder.AppendLine(this.PvIdString + ".songinfo.music=---");
            stringBuilder.AppendLine(this.PvIdString + ".songinfo.pv_editor=" + this.PvEditor);
            stringBuilder.AppendLine("# --- MODIFIERS ---");
            stringBuilder.AppendLine(this.PvIdString + ".sudden_timing=0.6");
            stringBuilder.AppendLine("# --- EOF ---");
            return PvDatabaseInfo.SortDbStrings(stringBuilder.ToString());
        }

        private void AppendFields(StringBuilder stringBuilder)
        {
            for (int i = 0; i < Stages.Count; i++)
            {
                string stageType = Enum.IsDefined(typeof(SprEditStages), (SprEditStages)Stages[i]) ? "spr_set_back" : "stage";

                stringBuilder.AppendLine($"# field.{(i + 1):D2}.name={(StageName)Stages[i]}");

                var adjustedField = Settings.UserSettings.FieldLookup.FirstOrDefault(f => f.InputField == Stages[i].ToString());

                if (adjustedField.InputField != null && adjustedField.OutputFields != null && adjustedField.OutputFields.Count > 0)
                {
                    if (adjustedField.OutputFields.Count == 1 && !adjustedField.OutputFields[0].Contains("="))
                    {
                        stringBuilder.AppendLine($"# {Stages[i]} => {adjustedField.OutputFields[0]}");
                        stringBuilder.AppendLine($"{PvIdString}.field.{(i + 1):D2}.{stageType}={adjustedField.OutputFields[0]}");
                    }
                    else
                    {
                        var outputStage = adjustedField.OutputFields.LastOrDefault(f => f.Contains("stage="));
                        if (outputStage != null)
                        {
                            var split = outputStage.Split(new char[] { '=' }, 2);
                            if (split.Length > 1)
                            {
                                stringBuilder.AppendLine($"# {Stages[i]} => {split[1]}");
                            }
                        }
                        foreach (var output in adjustedField.OutputFields)
                        {
                            stringBuilder.AppendLine($"{PvIdString}.field.{(i + 1):D2}.{output}");
                        }
                    }
                }
                else
                {
                    stringBuilder.AppendLine($"{PvIdString}.field.{(i + 1):D2}.{stageType}={Stages[i]}");
                }
            }
            stringBuilder.AppendLine($"{PvIdString}.field.length={Stages.Count}");
        }

        private void AppendDiva2ndFields(StringBuilder stringBuilder)
        {
            for (int i = 0; i < Diva2ndStages.Count; i++)
            {
                string stageType = Enum.IsDefined(typeof(EditMode.Diva2nd.StageBack), (EditMode.Diva2nd.StageBack)Diva2ndStages[i]) ? "spr_set_back" : "stage";

                stringBuilder.AppendLine($"{PvIdString}.field.{(i + 1):D2}.{stageType}={(Diva2ndStages[i].ToString().ToUpper())}");
            }
            stringBuilder.AppendLine($"{PvIdString}.field.length={Diva2ndStages.Count}");
        }

        public List<string> GetFieldDb()
        {
            var sb = new StringBuilder();

            sb.AppendLine($"# EditScript.Import : {DateTime.Now.ToShortDateString()}");
            sb.AppendLine($"# --- {PvIdString.ToUpper()} ---");

            for (int i = 0; i < Stages.Count; i++)
            {
                string stageType = Enum.IsDefined(typeof(SprEditStages), (SprEditStages)Stages[i]) ? "spr_set_back" : "stage";
                sb.AppendLine($"# field.{(i + 1):D2}.name={(StageName)Stages[i]}");
                sb.AppendLine($"{PvIdString}.field.{(i + 1):D2}.{stageType}={Stages[i]}");
            }
            sb.AppendLine($"{PvIdString}.field.length={Stages.Count}");

            sb.AppendLine($"# --- EOF ---");

            return SortDbStrings(sb.ToString());
        }

        public List<string> GetFtFieldDb()
        {
            var sb = new StringBuilder();

            sb.AppendLine($"# EditScript.Import : {DateTime.Now.ToShortDateString()}");
            sb.AppendLine($"# --- {PvIdString.ToUpper()} ---");

            AppendFields(sb);

            sb.AppendLine($"# --- EOF ---");

            return SortDbStrings(sb.ToString());
        }

        public List<string> GetDiva2ndFieldDb()
        {
            var sb = new StringBuilder();

            sb.AppendLine($"# DIVA 2nd EditScript.Import : {DateTime.Now.ToShortDateString()}");
            sb.AppendLine($"# --- {PvIdString.ToUpper()} ---");

            AppendDiva2ndFields(sb);

            sb.AppendLine($"# --- EOF ---");

            return SortDbStrings(sb.ToString());
        }

        public static List<string> SortDbStrings(string unsorted)
        {
            // TODO:
            var list = new List<string>();
            list.AddRange(unsorted.Replace("\r", "").Split(new[] { '\n' }));
            list.OrderBy(s => s);
            return list;
        }
    }
}
